package org.xbdframework.scheduling.quartz;

import org.quartz.*;

/**
 * 定时任务控制器
 *
 * @author luas
 * @since 4.3
 */
public abstract class QuartzTaskHandler {

	protected Scheduler scheduler;

	/**
	 * 动态添加任务
	 * <p>
	 * 将声明的{@code QuartzTask}添加到{@code Scheduler}中
	 * </p>
	 * @param quartzTask 定时任务信息
	 *
	 * @see QuartzTask 定时任务信息
	 * @throws SchedulerException
	 * 如果声明的定时任务不能被添加到{@code Scheduler}中，或者{@code Scheduler}内部异常
	 */
	public abstract void addTask(QuartzTask quartzTask) throws SchedulerException;

	/**
	 * 动态添加任务
	 * <p>
	 * 将声明的{@code QuartzTask}添加到{@code Scheduler}中
	 * </p>
	 * @param quartzTasks 定时任务信息列表
	 *
	 * @see QuartzTask 定时任务信息
	 * @see #addTask(QuartzTask)
	 * @throws SchedulerException
	 * 如果声明的定时任务不能被添加到{@code Scheduler}中，或者{@code Scheduler}内部异常
	 */
	public abstract void addTask(QuartzTask... quartzTasks) throws SchedulerException;

	/**
	 * 动态添加任务
	 * <p>
	 * 将声明的{@code QuartzTask}更新到{@code Scheduler}中，任务可以是正在运行的状态，也没问题
	 * </p>
	 * @param quartzTask 定时任务信息
	 *
	 * @see QuartzTask 定时任务信息
	 * @see #addTask(QuartzTask)
	 * @throws SchedulerException
	 * 如果声明的定时任务不能被更新到{@code Scheduler}中，或者{@code Scheduler}内部异常
	 */
	public abstract void updateTask(QuartzTask quartzTask) throws SchedulerException;

	/**
	 * 动态添加任务
	 * <p>
	 * 将声明的{@code QuartzTask}更新到{@code Scheduler}中，任务可以是正在运行的状态，也没问题
	 * </p>
	 * @param quartzTasks 定时任务信息列表
	 *
	 * @see QuartzTask 定时任务信息
	 * @see #updateTask(QuartzTask)
	 * @throws SchedulerException
	 * 如果声明的定时任务不能被更新到{@code Scheduler}中，或者{@code Scheduler}内部异常
	 */
	public abstract void updateTask(QuartzTask... quartzTasks) throws SchedulerException;

	/**
	 * 暂停声明的{@code QuartzTask}任务
	 *
	 * @see QuartzTask
	 * @param quartzTask 定时任务信息
	 * @throws SchedulerException 如果声明的定时任务不能被暂停，或者{@code Scheduler}内部异常
	 */
	public abstract void pauseTask(QuartzTask quartzTask) throws SchedulerException;

	/**
	 * 暂停声明的{@code QuartzTask}任务
	 *
	 * @see QuartzTask
	 * @see #pauseTask(QuartzTask)
	 * @param quartzTasks 定时任务信息列表
	 * @throws SchedulerException 如果声明的定时任务不能被暂停，或者{@code Scheduler}内部异常
	 */
	public abstract void pauseTask(QuartzTask... quartzTasks) throws SchedulerException;

	/**
	 * 暂停任务
	 * <p>
	 * 将{@code Scheduler}中的所有任务暂停
	 * </p>
	 *
	 * @see QuartzTask 定时任务信息
	 * @throws SchedulerException 如果定时任务不能被暂停，或者{@code Scheduler}内部异常
	 */
	public abstract void pauseTask() throws SchedulerException;

	/**
	 * 继续任务
	 *
	 * <p>
	 * 将已暂停的任务恢复运行状态
	 * </p>
	 *
	 * @see QuartzTask
	 * @param quartzTask 定时任务信息
	 * @throws SchedulerException 如果定时任务不能恢复，或者{@code Scheduler}内部异常
	 */
	public abstract void resumeTask(QuartzTask quartzTask) throws SchedulerException;

	/**
	 * 继续任务
	 *
	 * <p>
	 * 将已暂停的任务恢复运行状态
	 * </p>
	 *
	 * @see QuartzTask
	 * @see #resumeTask(QuartzTask)
	 * @param quartzTasks 定时任务信息列表
	 * @throws SchedulerException 如果定时任务不能恢复，或者{@code Scheduler}内部异常
	 */
	public abstract void resumeTask(QuartzTask... quartzTasks) throws SchedulerException;

	/**
	 * 删除任务
	 *
	 * <p>
	 * 将声明的{@code QuartzTask}从{@code Scheduler}中删除
	 * </p>
	 *
	 * @see QuartzTask
	 * @param quartzTask 定时任务信息
	 * @throws SchedulerException 如果定时任务不能被删除，或者{@code Scheduler}内部异常
	 */
	public abstract void deleteTask(QuartzTask quartzTask) throws SchedulerException;

	/**
	 * 删除任务
	 *
	 * <p>
	 * 将声明的{@code QuartzTask}从{@code Scheduler}中删除
	 * </p>
	 *
	 * @see QuartzTask
	 * @see #deleteTask(QuartzTask)
	 * @param quartzTasks 定时任务信息列表
	 * @throws SchedulerException 如果定时任务不能被删除，或者{@code Scheduler}内部异常
	 */
	public abstract void deleteTask(QuartzTask... quartzTasks) throws SchedulerException;

	/**
	 * 根据定时任务信息组织CronScheduleBuilder
	 *
	 * @see CronScheduleBuilder
	 * @see QuartzTask
	 * @see CronScheduleBuilder
	 * @param quartzTask 定时任务信息
	 * @return CronScheduleBuilder 基于Cron表达式的{@link org.quartz.ScheduleBuilder}
	 */
	public CronScheduleBuilder initCronScheduleBuilder(QuartzTask quartzTask) {
		CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
				.cronSchedule(quartzTask.getCronExpression());

		// 以当前时间为触发频率立刻触发一次执行，然后按照Cron频率依次执行
		if (quartzTask
				.getMisfireInstruction() == CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
			cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
		}
		else if (quartzTask
				.getMisfireInstruction() == CronTrigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY) {
			// 以错过的第一个频率时间立刻开始执行，重做错过的所有频率周期后，当下一次触发频率发生时间大于当前时间后，再按照正常的Cron频率依次执行
			cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
		}
		else if (quartzTask
				.getMisfireInstruction() == CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING) {
			// 不触发立即执行，等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
			cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
		}

		return cronScheduleBuilder;
	}

	/**
	 * 根据任务名称、任务分组获取定时任务调度器中的该任务触发器
	 * @param name 触发器名称
	 * @param group 触发器分组
	 * @return CronTrigger 基于Cron表达式的定时任务触发器
	 * @throws SchedulerException 名称、分组为空、触发器不存在、或者{@code Scheduler}内部异常
	 */
	public CronTrigger getTrigger(String name, String group) throws SchedulerException {
		CronTrigger cronTrigger = (CronTrigger) scheduler
				.getTrigger(new TriggerKey(name, group));

		return cronTrigger;
	}

	/**
	 * 获取当前<code>Scheduler</code>instance Id
	 * @return 当前<code>Scheduler</code>的instance Id
	 * @throws SchedulerException {@code Scheduler}内部异常
	 */
	public String getSchedulerInstanceId() throws SchedulerException {
		return scheduler.getSchedulerInstanceId();
	}

	public Scheduler getScheduler() {
		return scheduler;
	}

	public void setScheduler(Scheduler scheduler) {
		this.scheduler = scheduler;
	}

}
